package com.test.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Scanner;
import java.util.Set;

public class NioSocketClient {
    private String serverIp;
    private int serverPort;
    private Selector selector;
    private SocketChannel socketChannel;
    private ByteBuffer readBuffer;
    private ByteBuffer writeBuffer;
    private String readMsg;
    private String writeMsg;

    public NioSocketClient() {
        this("localhost", 8111, 512);
    }

    public NioSocketClient(String serverIp, int serverPort, int bufferLength) {
        this.serverIp = serverIp;
        this.serverPort = serverPort;
        readBuffer = ByteBuffer.allocate(bufferLength);
        writeBuffer = ByteBuffer.allocate(bufferLength);
        init();
        listen();
    }

    private void init() {
        try {
            socketChannel = SocketChannel.open();
            socketChannel.configureBlocking(false);
            selector = Selector.open();
            socketChannel.register(selector, SelectionKey.OP_CONNECT);
            socketChannel.connect(new InetSocketAddress(serverIp, serverPort));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void listen() {
        try {
            while (true) {
                selector.select();//阻塞，获取事件
                Set<SelectionKey> keys = selector.selectedKeys();
                for (SelectionKey key : keys) {
                    handler(key); //处理事件
                }
                keys.clear();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void handler(SelectionKey key) {
        SocketChannel channel;
        try {
            if (key.isConnectable()) {//连接上了
                channel = (SocketChannel) key.channel();
                if (channel.isConnectionPending()) {//验证连接是否通畅
                    channel.finishConnect();//完成连接
                    writeMsg = "连接服务端成功！";
                    writeBuffer.clear();
                    writeBuffer.put(writeMsg.getBytes());
                    writeBuffer.flip();
                    channel.write(writeBuffer);
                    channel.register(selector, SelectionKey.OP_READ);
                    write(channel);
                }
            } else if (key.isReadable()) {
                channel = (SocketChannel) key.channel();
                readBuffer.clear();
                int len = channel.read(readBuffer);
                if (len > 0) {
                    readMsg = new String(readBuffer.array(), 0, len);
                    System.out.println(readMsg);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void write(SocketChannel channel) {
        new Thread(() -> {
            try {
                Scanner scanner = new Scanner(System.in);
                while (true) {
                    System.out.println("请输入聊天内容");
                    writeMsg = scanner.nextLine();
                    writeBuffer.clear();
                    writeBuffer.put(writeMsg.getBytes());
                    writeBuffer.flip();
                    channel.write(writeBuffer);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();

    }
}
